/*
 *	utils.c
 *  Release $Name: SECUREAGENT-LIB $
 *
 *	Utility functions for the secure agent library
 */
/*
 *	Copyright (c) Philipp Haindl, 2011-2012. All Rights Reserved.
 *	The latest version of this code is available at http://www.thinkr.at
 *
 *	This software is open source; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 *	This General Public License does NOT permit incorporating this software
 *	into proprietary programs.
 *
 *	This program is distributed in WITHOUT ANY WARRANTY; without even the
 *	implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *	See the GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program; if not, write to the Free Software
 *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *	http://www.gnu.org/copyleft/gpl.html
 */
/******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <sys/sem.h>
#include <time.h>
#include "jni.h"
#include "jvmti.h"
#include "utils.h"

int jvmti_version_check(jvmtiEnv *jvmti)
{
    jint cmajor, cminor, cmicro;
    jint rmajor, rminor, rmicro;
    jint runtime_version;
    jint cver, rver;
    jvmtiError err;

    /* get compile time JVMTI version */
    cver = JVMTI_VERSION;

    /* get runtime JVMTI version */
    err = (*jvmti)->GetVersionNumber(jvmti, &rver);

    if (err != JVMTI_ERROR_NONE)
    {
    	(void)fprintf(stderr, "Unable to retrieve runtime JVMTI version!\n");
    }

    cmajor = (cver & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR;
    cminor = (cver & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR;
    cmicro = (cver & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO;
    rmajor = (rver & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR;
    rminor = (rver & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR;
    rmicro = (rver & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO;

    (void)fprintf(stdout, "Compile Time JVMTI Version: %d.%d.%d (0x%08x)\n", cmajor, cminor, cmicro, cver);
    (void)fprintf(stdout, "Run Time JVMTI Version: %d.%d.%d (0x%08x)\n", rmajor, rminor, rmicro, rver);

    if (cmajor != rmajor || cminor != rminor)
    {
    	/* version mismatch */
    	return -1;
    }

    return 1;
}

int jvmti_set_capabilities(jvmtiEnv *env)
{
	jvmtiCapabilities capa;
	jvmtiError err;

	(void)memset(&capa, 0, sizeof(capa));

	/*
	 * we need capabilities to:
	 * - set and unset breakpoints
	 * - modify local values
	 * - be notified about method entries
	 * - be notified about method exits
	 */
	capa.can_generate_breakpoint_events = 1;
	capa.can_access_local_variables = 1;
	capa.can_generate_method_entry_events = 1;
	capa.can_generate_method_exit_events = 1;

	/* set JVMTI capabilities */
	err = (*env)->AddCapabilities(env, &capa);

	if (err != JVMTI_ERROR_NONE)
	{
		(void)fprintf(stderr, "Unable to set all capabilities (err=%d) !\n", err);
		return -1;
	}

	return 0;
}
